home *** CD-ROM | disk | FTP | other *** search
- #include "MacHeaders7"
- #include "Utils.h"
- #include "MSM.h"
-
- #include <Balloons.h>
- #include <Processes.h>
-
- traps Patches[myLast+1] = {
- 0xA93D,0,0, /* MenuSelect */
- 0xA96D,0,0, /* Draw1Control */
- 0xA912,0,0, /* InitWindows */
- 0x0000,0,0 /* Last */
- };
-
- /********************************************************************************/
-
- /* it is necessary inside traps to have a convenient way of vectoring back
- to the "old" trap routine. w/o multi-seg code resources, and if the
- compiler were smart enough, this could be done with PC-relative code,
- something like:
- asm {
- move.l Patches[myMove].oldAddress,-(a7)
- rts
- }
- Note that this code preserves all registers. Unfortunately, this code
- does not work in the world of Think C since globals are accessed relative
- to a4. So instead, we call a routine named vector which performs like
- LoadSeg - it converts the call to vector into a jsr.l or jmp.l to the
- address in question. This makes future executions of this code faster,
- too. (For those who are freaks about self-modifying code, it is possible
- to modify vector in such a way that it acts as if there were a JMP or JSR,
- without modifying any code. This would, however, be much harder to follow
- when debugging through the patch code, and it would be slower, since every
- time through, the address would have to be re-computed. As luck would
- have it, the non-self-modifying code takes up less space, and while I was
- debugging through it to make sure it worked, it turned up a bug in the
- INIT I was writing where I was accidentally modifying the wrong entry in
- the trap table. So it's included here for completeness sake and as yet
- another way of making sure an INIT is squeaky clean.
-
- The call to vector should be:
- asm {
- jsr vector
- dc.w myMove
- };
- Sometimes you want to do a jsr rather than a jump. This is simple,
- just invert the selector word:
- asm {
- jsr vector
- dc.w ~myMove
- }
- Just to make things complete, we define 2 macros to invoke the vector:
- */
-
- #define VectorJMP(myTrap) \
- jsr vector \
- dc.w myTrap
-
- #define VectorJSR(myTrap) \
- jsr vector \
- dc.w ~myTrap
-
- #define self_modifying_code 1
-
- #if self_modifying_code
-
- static void vector(short this_parameter_forces_a_link_instruction) {
- asm {
- _SetUpA4
- movem.l a0/a1/d0/d1,-(a7) ; don’t disturb the registers!
- move.w #0x4EF9,d1 ; 4EF9 = JMP.L
- move.l 4(a6),a1 ; a1 is now the return address.
- move.w (a1),d0 ; d0 is now the trap #.
- bge.s @JMP
-
- JSR: not.w d0
- move.w #0x4EB9,d1 ; 4EB9 = JSR.L
-
- JMP: subq #4,a1 ; a1 is now the point of original call.
- move.l a1,4(a6) ; save it so we return there.
- lea Patches,a0 ; get the address of Patches array in a0.
- mulu.w #sizeof(traps),d0 ; d0 is now the offset into Patches for this particular trap.
- move.w d1,(a1)+ ; d1 = JMP.L or JSR.L
- move.l OFFSET(traps,oldAddress)(a0,d0),(a1)+
- jsr FlushCache ; wipe the cache because we modified our own code.
- movem.l (a7)+,a0/a1/d0/d1 ; save the registers.
- _RestoreA4
- }; /* and returning takes us back to the jump! */
- }
-
- #else
-
- static void vector(void) {
- asm {
- link a6,#-4
- move.l (a6),(a7) ; so we can easily leave extra space on the stack.
- movem.l a0/d0,-(a7) ; don’t disturb the registers!
- move.l 4(a6),a0 ; a1 is now the address of the inline param to vector.
- move.w (a0)+,d0 ; d0 is now the trap #, and a0 is the real return address.
- move.l a0,4(a6) ; save the new return address for the JSR case.
- _SetUpA4
- lea Patches,a0 ; get the address of Patches array in a0.
- _RestoreA4 ; don’t need a4 anymore.
- tst.w d0
- bge.s @JMP ; negative d0 means we came from the JSR macro.
-
- JSR: not.w d0 ; d0 is now the un-inverted trap #.
- subq #4,a6 ; this puts 4 more bytes on the stack and saves the
- ; return address of the vector call on the stack. In
- ; the non-JSR case, the return address gets obliterated.
-
- JMP: mulu.w #sizeof(traps),d0 ; d0 is now the offset into Patches for this particular trap.
- move.l OFFSET(traps,oldAddress)(d0,a0),4(a6)
- movem.l (a7)+,a0/d0
- unlk a6
- ; rts ; this returns to the old trap address, which, either returns to the
- ; instruction after the VectorJSR macro or in the case of the
- ; VectorJMP macro, to wherever.
- };
- }
-
- #endif
-
- /********************************************************************************/
-
- void FixA4(Handle h) {
- asm {
- move.l h,a0
- GetHandleSize
- tst.l d0
- ble.s @LX
- move.l (a0),a0
- LP: subq #2,d0
- beq @LX
- cmpi.w #0x2F0C,(a0)+ ; 2F0C == 'move.l a4,-(a7)'
- bne.s @LP
- subq #2,d0
- cmpi.w #0x49F9,(a0)+ ; 49F9 == 'lea 0x????,a4'
- bne.s @LP
- cmpi.l #'rga4',(a0) ; rga4 is what we want to replace
- bne.s @LP
- move.l a4,(a0)
- bra.s @LP
- LX:
- }
- }
-
- extern char Launched : 0x910; /* if non-positive, we’re not running yet. */
-
- CGrafPort *MSMPort;
- long NeedBlack;
- static short countDown = 8;
-
- static void MakeTheHoleBlack(void) {
- ProcessSerialNumber us, front;
- GrafPtr oldPort;
-
- // let's be really paranoid about when we do this.
- // let's me sure the window manager exists, at least one program
- // has been launched, there's a real menu bar, resources are set
- // to be loaded, we have at least one menu in the menu bar, and
- // there's at least 2K of stack space.
- if (WWExist != 0 || Launched <= 0 || MBarHeight <= 0 || ResLoad == 0 ||
- jbMenuList == 0 || *jbMenuList == 0 || (**jbMenuList).lastMenu == 0 ||
- StackSpace() < 2048) return;
-
- // and make sure the front process is us.
- GetFrontProcess(&us);
- GetCurrentProcess(&front);
- if (us.highLongOfPSN != front.highLongOfPSN) return;
- if (us.lowLongOfPSN != front.lowLongOfPSN) return;
-
- if (countDown > 0) {
- countDown--;
- return;
- }
-
- if (TickCount() > NeedBlack) {
- GetPort(&oldPort);
- SetPort(MSMPort);
- FillRgn(gMysterious, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");
- NeedBlack = TickCount() + 300;
- SetPort(oldPort);
- }
- }
-
- static long last_chk;
- long last_non_dialog;
- WindowPeek lastWP;
-
- static short Microsoft, CopyOnce;
-
- void pJGNEfilter(short what, EventRecord *ep) {
- EventRecord er;
- WindowPeek wp;
- Rect r;
- Point pt = ep->where, midpt;
- long now = TickCount();
-
- if (what == 0) {
- er.what = nullEvent;
- ep = &er;
- }
- switch(ep->what) {
- case nullEvent:
- wp = (WindowPeek) FrontWindow();
- if (wp != NULL && wp->windowKind == 2 && GetWVariant(wp) == 1) {
- CopyOnce = FALSE;
- if (lastWP != wp) {
- if (now - last_non_dialog > 600) {
- r = (**wp->strucRgn).rgnBBox;
- if (PtInRect(pt, &r)) {
- QueueSound(7);
- } else {
- midpt.h = (r.left + r.right) / 2;
- midpt.v = (r.top + r.bottom) / 2;
- if (pt.h - pt.v > midpt.h - midpt.v) {
- if (pt.h + pt.v > midpt.h + midpt.v) {
- QueueSound(8);
- } else {
- QueueSound(10);
- }
- } else {
- if (pt.h + pt.v > midpt.h + midpt.v) {
- QueueSound(11);
- } else {
- QueueSound(9);
- }
- }
- }
- last_non_dialog = now;
- }
- } else {
- last_non_dialog = now;
- }
- } else {
- char title[256];
- if (wp) GetWTitle(wp, title);
- if (wp && title[0] == 4 && 'Copy' == *(long*)&title[1]) {
- if (!CopyOnce) {
- QueueSound(12);
- CopyOnce = TRUE;
- }
- } else {
- CopyOnce = FALSE;
- last_non_dialog = now;
- if (*(long *)0x911 == 'Micr') {
- if (!Microsoft) {
- Microsoft = TRUE;
- QueueSound(3);
- }
- } else {
- Microsoft = FALSE;
- }
- }
- }
- case updateEvt:
- MakeTheHoleBlack();
- break;
- case mouseDown:
- if (PtInRgn(pt, gMysterious)) {
- QueueSound(6);
- }
- case mouseUp:
- case keyDown:
- last_non_dialog = now;
- break;
- }
- }
-
- pascal long pMenuSelect(Point pt) {
- long result;
-
- asm {
- move.l 12(a6),-(a7)
- move.l pt,-(a7)
- VectorJSR(myMenuSelect)
- move.l (a7)+,result
- _SetUpA4
- movem.l a0/a1/d0/d1/d2,-(a7)
- }
-
- if (MenuDisable == 0xBF960003) {
- QueueSound(1); // PlayNamedSound("\pNot!", 0);
- HMSetBalloons(FALSE);
- } else if (result == 0x01050001) {
- QueueSound(4);
- } else if (result == 0x01050005) {
- QueueSound(5);
- } else {
- }
-
- asm {
- movem.l (a7)+,a0/a1/d0/d1/d2
- _RestoreA4
- }
-
- return result;
- }
-
- pascal void pDraw1Control(ControlHandle ch) {
- uchar text[256];
- GetCTitle(ch, text);
- asm {
- _SetUpA4
- }
- if (GetCtlValue(ch) == TRUE && jbRelString(text, "\pWarn before emptying") == 0) {
- QueueSound(2); // PlayNamedSound("\pWimp!", 0);
- }
- asm {
- _RestoreA4
- unlk a6
- VectorJMP(myDraw1Control);
- }
- }
-
- extern long NeedBlack;
- RgnHandle gMysterious;
- static void PunchOut(void) {
- GrafPtr oldPort;
- Rect r, scrn;
- THz z;
-
- GetPort(&oldPort);
- SetPort(WMgrCPort);
- z = GetZone();
- SetZone(SystemZone());
- if (!gMysterious) {
- gMysterious = NewRgn();
- OpenRgn();
- r.top = 50;
- r.left = 50;
- r.bottom = 150;
- r.right = 150;
- FrameOval(&r);
- CloseRgn(gMysterious);
- }
- r = (**gMysterious).rgnBBox;
- OffsetRgn(gMysterious, WMgrCPort->portRect.right - r.right, WMgrCPort->portRect.bottom - r.bottom);
- PaintRgn(gMysterious);
- DiffRgn(GrayRgn, gMysterious, GrayRgn);
- SetZone(z);
- SetPort(oldPort);
- NeedBlack = TickCount();
- }
-
- pascal void pInitWindows(void) {
- asm {
- VectorJSR(myInitWindows);
- movem.l d0/d1/d2/a0/a1/a4,-(a7)
- link a6,#0
- _SetUpA4
- }
- PunchOut();
- asm {
- unlk a6
- movem.l (a7)+,d0/d1/d2/a0/a1/a4
- }
- }